home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / fun / nethack.a1 < prev    next >
Text File  |  1988-12-02  |  56KB  |  2,242 lines

  1. Path: xanth!nic.MR.NET!hal!cwjcc!gatech!rutgers!mit-eddie!ll-xn!adelie!infinet!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i068:  nethack - D&D-like game (amiga additions), Part01/02
  5. Message-ID: <10399@swan.ulowell.edu>
  6. Date: 1 Dec 88 23:37:47 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2231
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: u211344@hnykun11.bitnet (Olaf 'Rhialto' Seibert)
  12. Posting-number: Volume 2, Issue 68
  13. Archive-name: fun/nethack.a1
  14.  
  15. [The Amiga additional files plus the diffs, when applied to the
  16. original nethack source, should produce an Amiga executable version of
  17. nethack.  ..Bob]
  18.  
  19. #    This is a shell archive.
  20. #    Remove everything above and including the cut line.
  21. #    Then run the rest of the file through sh.
  22. #----cut here-----cut here-----cut here-----cut here----#
  23. #!/bin/sh
  24. # shar:    Shell Archiver
  25. #    Run the following text with /bin/sh to create:
  26. #    amigaDos.c
  27. #    amigaMenu.c
  28. #    amigaTTY.c
  29. #    amigaTermcap.c
  30. #    amigaUnix.c
  31. #    amigaWindow.c
  32. # This archive created: Thu Dec  1 17:50:06 1988
  33. cat << \SHAR_EOF > amigaDos.c
  34. /*    SCCS Id: @(#)amigaDos.c msdos.c - Amiga version   2.3    88/07/24
  35. /* An assortment of MSDOS functions.
  36.  */
  37.  
  38. #include <stdio.h>
  39. #include "hack.h"
  40.  
  41. #undef TRUE
  42. #undef FALSE
  43. #undef COUNT
  44.  
  45. #include <libraries/dos.h>
  46.  
  47. extern char Initialized;
  48.  
  49. struct FileLock *Lock(), *CurrentDir(); /* Cheating - BCPL pointers */
  50. struct FileHandle *Open();              /* Cheating - BCPL pointer */
  51. long Read(), Write(), IoErr(), AvailMem();
  52. void *malloc();
  53. char *rindex(), *index();
  54.  
  55. int Enable_Abort = 0;   /* for stdio package */
  56.  
  57. /* Initial path, so we can find NetHack.cnf */
  58.  
  59. char PATH[PATHLEN] = "Ram:;df0:;NetHack:";
  60.  
  61. void
  62. flushout()
  63. {
  64.     (void) fflush(stdout);
  65. }
  66.  
  67. getuid() {
  68.     return 1;
  69. }
  70.  
  71. /*
  72.  *  Actually make up a process id.
  73.  *  Makes sure one can mess less with saved levels...
  74.  */
  75.  
  76. int getpid()
  77. {
  78.     static short pid;
  79.  
  80.     while (pid == 0) {
  81.         struct DateStamp dateStamp;
  82.         pid = rnd(30000);
  83.         pid += DateStamp(&dateStamp);    /* More or less random */
  84.         pid ^= (short) (dateStamp.ds_Days >> 16) ^
  85.                (short) (dateStamp.ds_Days)       ^
  86.                (short) (dateStamp.ds_Minute)     +
  87.                (short) (dateStamp.ds_Tick);
  88.         pid %= 30000;
  89.     }
  90.  
  91.     return pid;
  92. }
  93.  
  94. char *
  95. getlogin() {
  96.     return ((char *) NULL);
  97. }
  98.  
  99. int
  100. abs(x)
  101. int x;
  102. {
  103.     return x < 0? -x: x;
  104. }
  105.  
  106. #ifdef REDO
  107. tgetch() {
  108.     char ch, popch();
  109.  
  110.     if (!(ch = popch())) {
  111.         ch = WindowGetchar();
  112.     }
  113.     return ((ch == '\r') ? '\n' : ch);
  114. }
  115. #else /* REDO /**/
  116. tgetch() {
  117.     char ch;
  118.  
  119.     ch = WindowGetchar();
  120.     return ((ch == '\r') ? '\n' : ch);
  121. }
  122. #endif /* REDO /**/
  123.  
  124.  
  125. #ifdef DGK
  126. # include <ctype.h>
  127. # include <fcntl.h>
  128.  
  129. # define Sprintf (void) sprintf
  130.  
  131. # ifdef SHELL
  132. dosh()
  133. {
  134.     pline("No mysterious force prevented you from using multitasking.");
  135.     return 0;
  136. }
  137. # endif /* SHELL */
  138.  
  139.  
  140. /* construct the string  file.level */
  141. void
  142. name_file(file, level)
  143. char *file;
  144. int level;
  145. {
  146.     char *tf;
  147.  
  148.     if (tf = rindex(file, '.'))
  149.         Sprintf(tf+1, "%d", level);
  150. }
  151.  
  152. #define ID_DOS1_DISK    'DOS\1'
  153.  
  154. /*
  155.  *  This routine uses an approximation of the free bytes on a disk.
  156.  *  How large a file you can actually write depends on the number of
  157.  *  extension blocks you need for it.
  158.  *  An iterative approach is used that (hopefully) mimics the AmigaDOG
  159.  *  (yuck, tripos) block allocation sequence used when a file grows.
  160.  */
  161. long
  162. freediskspace(path)
  163. char *path;
  164. {
  165.     register long freeBytes = 0;
  166.     register struct InfoData *infoData; /* Remember... longword aligned */
  167.     char fileName[32];
  168.  
  169.     /*
  170.      *  Find a valid path on the device of which we want the free space.
  171.      *  If there is a colon in the name, it is an absolute path
  172.      *  and all up to the colon is everything we need.
  173.      *  Remember slashes in a volume name are allowed!
  174.      *  If there is no colon, it is relative to the current directory,
  175.      *  so must be on the current device, so "" is enough...
  176.      */
  177.     {
  178.         register char *colon;
  179.  
  180.         strncpy(fileName, path, sizeof(fileName)-1);
  181.         fileName[31] = 0;
  182.         if (colon = index(fileName, ':'))
  183.             colon[1] = '\0';
  184.         else
  185.             fileName[0] = '\0';
  186.     }
  187.  
  188.     if (infoData = malloc(sizeof(*infoData))) {
  189.         struct FileLock *fileLock;  /* Cheating */
  190.         if (fileLock = Lock(fileName, SHARED_LOCK)) {
  191.             if (Info(fileLock, infoData)) {
  192.                 /* We got a kind of DOS volume, since we can Lock it. */
  193.                 /* Calculate number of blocks available for new file */
  194.                 /* Kludge for the ever-full VOID: (oops RAM:) device */
  195.                 if (infoData->id_UnitNumber == -1 &&
  196.                     infoData->id_NumBlocks == infoData->id_NumBlocksUsed) {
  197.                     freeBytes = AvailMem(0L) - 48*1024;
  198.                     /* Just a stupid guess at the */
  199.                     /* Ram-Handler overhead per block: */
  200.                     freeBytes -= freeBytes/16;
  201.                 } else {
  202.                     /* Normal kind of DOS file system device/volume */
  203.                     register long fileBlocks;
  204.                     register long extensionPointers;
  205.                     freeBytes = infoData->id_NumBlocks -
  206.                                 infoData->id_NumBlocksUsed -
  207.                                 1;  /* for file header */
  208.                     if (infoData->id_DiskType == ID_DOS_DISK)
  209.                         /* BytesPerBlock is 488 on floppies */
  210.                         extensionPointers = (infoData->id_BytesPerBlock-200)/4;
  211.                     else
  212.                         /* Presumably it is 512 on ID_DOS1_DISK. */
  213.                         extensionPointers = (infoData->id_BytesPerBlock-224)/4;
  214.                     /* Number of blocks left to simulate */
  215.                     fileBlocks = freeBytes;
  216.                     /* Need another extension block? */
  217.                     while (fileBlocks > extensionPointers) {
  218.                         /* Get an extension block. One block less free. */
  219.                         freeBytes--;
  220.                         fileBlocks--;
  221.                         /* to accomodate 72 extra data blocks */
  222.                         fileBlocks -= extensionPointers;
  223.                     }
  224.                     freeBytes *= infoData->id_BytesPerBlock;
  225.                 }
  226.                 if (freeBytes < 0)
  227.                     freeBytes = 0;
  228.             }
  229.             UnLock(fileLock);
  230.         }
  231.         free(infoData);
  232.     }
  233.     return freeBytes;
  234. }
  235.  
  236.  
  237. long
  238. filesize(file)
  239. char *file;
  240. {
  241.     register struct FileLock *fileLock;
  242.     register struct FileInfoBlock *fileInfoBlock;
  243.     register long size = 0;
  244.  
  245.     if (fileInfoBlock = malloc(sizeof(*fileInfoBlock))) {
  246.         if (fileLock = Lock(file, SHARED_LOCK)) {
  247.             if (Examine(fileLock, fileInfoBlock)) {
  248.                 size = fileInfoBlock->fib_Size;
  249.             }
  250.             UnLock(fileLock);
  251.         }
  252.         free(fileInfoBlock);
  253.     }
  254.     return size;
  255. }
  256.  
  257. /*
  258.  *  On the Amiga, looking if a specific file exists is much faster
  259.  *  than sequentially reading a directory.
  260.  */
  261.  
  262. void
  263. eraseall(path, files)
  264. char *path, *files;
  265. {
  266.     char buf[FILENAME];
  267.     short i;
  268.     struct FileLock *fileLock, *dirLock;
  269.  
  270.     if (dirLock = Lock(path)) {
  271.         dirLock = CurrentDir(dirLock);
  272.  
  273.         strcpy(buf, files);
  274.         for (i = 0; i < MAXLEVEL; i++) {
  275.             name_file(buf, i);
  276.             if (fileLock = Lock(buf, SHARED_LOCK)) {
  277.                 UnLock(fileLock);
  278.                 DeleteFile(buf);
  279.             }
  280.         }
  281.  
  282.         UnLock(CurrentDir(dirLock));
  283.     }
  284. }
  285.  
  286. /* This size makes that most files can be copied with two Read()/Write()s */
  287.  
  288. #define COPYSIZE    4096
  289.  
  290. char *CopyFile(from, to)
  291. char *from, *to;
  292. {
  293.     register struct FileHandle *fromFile, *toFile;
  294.     register char *buffer;
  295.     register long size;
  296.     char *error = NULL;
  297.  
  298.     if (buffer = malloc(COPYSIZE)) {
  299.         if (fromFile = Open(from, MODE_OLDFILE)) {
  300.             if (toFile = Open(to, MODE_NEWFILE)) {
  301.                 while (size = Read(fromFile, buffer, (long)COPYSIZE)) {
  302.                     if (size != Write(toFile, buffer, size)) {
  303.                         error = "Write error";
  304.                         break;
  305.                     }
  306.                 }
  307.                 Close(toFile);
  308.             } else /* Can't open destination file */
  309.                 error = "Cannot open destination";
  310.             Close(fromFile);
  311.         } else /* Cannot open source file. Should not happen. */
  312.             error = "Huh?? Cannot open source??";
  313.         free(buffer);
  314.         return error;
  315.     } else /* Cannot obtain buffer for copying */
  316.         return "No Memory !";
  317. }
  318.  
  319. void
  320. copybones(mode)
  321. int mode;
  322. {
  323.     struct FileLock *fileLock;
  324.     char from[FILENAME], to[FILENAME];
  325.     char *frompath, *topath, *status;
  326.     short i;
  327.     extern int saveprompt;
  328.  
  329.     if (!ramdisk)
  330.         return;
  331.  
  332.     frompath = (mode != TOPERM) ? permbones : levels;
  333.     topath = (mode == TOPERM) ? permbones : levels;
  334.  
  335.     /* Remove any bones files in `to' directory. */
  336.     eraseall(topath, allbones);
  337.  
  338.     /* Copy `from' to `to' */
  339.     strcpy(from, frompath);
  340.     strcat(from, allbones);
  341.     strcpy(to, topath);
  342.     strcat(to, allbones);
  343.  
  344.     for (i = 1; i < MAXLEVEL; i++) {
  345.         name_file(from, i);
  346.         name_file(to, i);
  347.         if (fileLock = Lock(from, SHARED_LOCK)) {
  348.             UnLock(fileLock);
  349.             if (status = CopyFile(from, to))
  350.                 goto failed;
  351.         }
  352.     }
  353.  
  354.     /*
  355.      * The last file got there.  Remove the ramdisk bones files.
  356.      */
  357.     if (mode == TOPERM)
  358.         eraseall(frompath, allbones);
  359.     return;
  360.  
  361.     /* Last file didn't get there. */
  362.  
  363. failed:
  364.     msmsg("Cannot copy `%s' to `%s'\n(%s)\n", from, to, status);
  365.  
  366.     if (mode == TOPERM) {
  367.         msmsg("Bones will be left in `%s'\n",
  368.             *frompath ? frompath : hackdir);
  369.         return;
  370.     } else {
  371.         /* Remove all bones files on the RAMdisk */
  372.         eraseall(levels, allbones);
  373.         playwoRAMdisk();
  374.     }
  375. }
  376.  
  377. playwoRAMdisk()
  378. {
  379.     msmsg("Do you wish to play without a RAMdisk (y/n) ? ");
  380.  
  381.     /* Set ramdisk false *before* exit'ing (because msexit calls
  382.      * copybones)
  383.      */
  384.     ramdisk = FALSE;
  385.     if (getchar() != 'y') {
  386.         settty("Be seeing you ...\n");
  387.         exit(0);
  388.     }
  389.     set_lock_and_bones();
  390.     return;
  391. }
  392.  
  393. saveDiskPrompt(start)
  394. {
  395.     extern int saveprompt;
  396.     char buf[BUFSIZ], *bp;
  397.     struct FileLock *fileLock;
  398.  
  399.     if (saveprompt) {
  400.         /* Don't prompt if you can find the save file */
  401.         if (fileLock = Lock(SAVEF, SHARED_LOCK)) {
  402.             UnLock(fileLock);
  403.             return 1;
  404.         }
  405.         remember_topl();
  406.         home();
  407.         cl_end();
  408.         msmsg("If save file is on a SAVE disk, put that disk in now.\n");
  409.         cl_end();
  410.         msmsg("File name (default `%s'%s) ? ", SAVEF,
  411.             start ? "" : ", <Esc> cancels save");
  412.         getlin(buf);
  413.         home();
  414.         cl_end();
  415.         curs(1, 2);
  416.         cl_end();
  417.         if (!start && *buf == '\033')
  418.             return 0;
  419.  
  420.         /* Strip any whitespace. Also, if nothing was entered except
  421.          * whitespace, do not change the value of SAVEF.
  422.          */
  423.         for (bp = buf; *bp; bp++)
  424.             if (!isspace(*bp)) {
  425.                 strncpy(SAVEF, bp, PATHLEN);
  426.                 break;
  427.             }
  428.     }
  429.     return 1;
  430. }
  431.  
  432. /* Return 1 if the record file was found */
  433. static boolean
  434. record_exists()
  435. {
  436.     FILE *file;
  437.  
  438.     if (file = fopenp(RECORD, "r")) {
  439.         fclose(file);
  440.         return TRUE;
  441.     }
  442.     return FALSE;
  443. }
  444.  
  445. /* Prompt for game disk, then check for record file.
  446.  */
  447. void
  448. gameDiskPrompt()
  449. {
  450.     extern int saveprompt;
  451.  
  452.     if (record_exists())
  453.         return;
  454.  
  455.     if (saveprompt) {
  456.         (void) putchar('\n');
  457.         getreturn("when the GAME disk has been put in");
  458.     }
  459.  
  460.     if (!record_exists()) {
  461.         msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD);
  462.  
  463.         msmsg("If the GAME disk is not in, put it in now.\n");
  464.         getreturn("to continue");
  465.     }
  466. }
  467.  
  468. /* Read configuration */
  469. void
  470. read_config_file()
  471. {
  472.     char    tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN];
  473.     char    buf[BUFSZ], *bufp;
  474.     FILE    *fp, *fopenp();
  475.     extern  char plname[];
  476.     extern  int saveprompt;
  477.  
  478.     tmp_ramdisk[0] = 0;
  479.     tmp_levels[0] = 0;
  480.     if ((fp = fopenp(configfile, "r")) == NULL) {
  481.         msmsg("Warning: no configuration file!\n");
  482.         getreturn("to continue");
  483.         return;
  484.     }
  485.     while (fgets(buf, BUFSZ, fp)) {
  486.         if (*buf == '#')
  487.             continue;
  488.  
  489.         /* remove trailing whitespace */
  490.  
  491.         bufp = index(buf, '\n');
  492.         while (bufp > buf && isspace(*bufp))
  493.             bufp--;
  494.         if (bufp == buf)
  495.             continue;        /* skip all-blank lines */
  496.         else
  497.             *(bufp + 1) = 0;    /* 0 terminate line */
  498.  
  499.         /* find the '=' */
  500.         if (!(bufp = index(buf, '='))) {
  501.             msmsg("Bad option line: '%s'\n", buf);
  502.             getreturn("to continue");
  503.             continue;
  504.         }
  505.  
  506.         /* skip  whitespace between '=' and value */
  507.         while (isspace(*++bufp))
  508.             ;
  509.  
  510.         /* Go through possible variables */
  511.         if (!strncmp(buf, "HACKDIR", 4)) {
  512.             strncpy(hackdir, bufp, PATHLEN);
  513.  
  514.         } else if (!strncmp(buf, "RAMDISK", 3)) {
  515.             strncpy(tmp_ramdisk, bufp, PATHLEN);
  516.  
  517.         } else if (!strncmp(buf, "LEVELS", 4)) {
  518.             strncpy(tmp_levels, bufp, PATHLEN);
  519.  
  520.         } else if (!strncmp(buf, "OPTIONS", 4)) {
  521.             parseoptions(bufp, TRUE);
  522.             if (plname[0])        /* If a name was given */
  523.                 plnamesuffix();    /* set the character class */
  524.  
  525.         } else if (!strncmp(buf, "SAVE", 4)) {
  526.             char *ptr;
  527.             if (ptr = index(bufp, ';')) {
  528.                 *ptr = '\0';
  529.                 if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
  530.                     saveprompt = FALSE;
  531.             }
  532.             (void) strncpy(SAVEF, bufp, PATHLEN);
  533.             append_slash(SAVEF);
  534. #ifdef GRAPHICS
  535.         } else if (!strncmp(buf, "GRAPHICS", 4)) {
  536.             unsigned int translate[MAXPCHARS];
  537.             int  i;
  538.  
  539.             if ((i = sscanf(bufp, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
  540.                 &translate[ 0], &translate[ 1], &translate[ 2],
  541.                 &translate[ 3], &translate[ 4], &translate[ 5],
  542.                 &translate[ 6], &translate[ 7], &translate[ 8],
  543.                 &translate[ 9], &translate[10], &translate[11],
  544.                 &translate[12], &translate[13], &translate[14],
  545.                 &translate[15], &translate[16], &translate[17])) < 0) {
  546.                     msmsg ("Syntax error in GRAPHICS\n");
  547.                     getreturn("to continue");
  548.             } /* Yuck! Worked only with low-byte first!!! */
  549. /*
  550.  * You could have problems here if you configure FOUNTAINS, SPIDERS or NEWCLASS
  551.  * in or out and forget to change the tail entries in your graphics string.
  552.  */
  553. #define SETPCHAR(f, n)    showsyms.f = (i > n) ? translate[n] : defsyms.f
  554.             SETPCHAR(stone, 0);
  555.             SETPCHAR(vwall, 1);
  556.             SETPCHAR(hwall, 2);
  557.             SETPCHAR(tlcorn, 3);
  558.             SETPCHAR(trcorn, 4);
  559.             SETPCHAR(blcorn, 5);
  560.             SETPCHAR(brcorn, 6);
  561.             SETPCHAR(door, 7);
  562.             SETPCHAR(room, 8);
  563.             SETPCHAR(corr, 9);
  564.             SETPCHAR(upstair, 10);
  565.             SETPCHAR(dnstair, 11);
  566.             SETPCHAR(trap, 12);
  567. #ifdef FOUNTAINS
  568.             SETPCHAR(pool, 13);
  569.             SETPCHAR(fountain, 14);
  570. #endif
  571. #ifdef NEWCLASS
  572.             SETPCHAR(throne, 15);
  573. #endif
  574. #ifdef SPIDERS
  575.             SETPCHAR(web, 16);
  576. #endif
  577. #ifdef SINKS
  578.             SETPCHAR(sink, 17);
  579. #endif
  580. #undef SETPCHAR
  581. #endif /* GRAPHICS */
  582.         } else if (!strncmp(buf, "PATH", 4)) {
  583.             strncpy(PATH, bufp, PATHLEN);
  584.  
  585.         } else {
  586.             msmsg("Bad option line: '%s'\n", buf);
  587.             getreturn("to continue");
  588.         }
  589.     }
  590.     fclose(fp);
  591.  
  592.     strcpy(permbones, tmp_levels);
  593.     if (tmp_ramdisk[0]) {
  594.         strcpy(levels, tmp_ramdisk);
  595.         if (strcmpi(permbones, levels))        /* if not identical */
  596.             ramdisk = TRUE;
  597.     } else
  598.         strcpy(levels, tmp_levels);
  599.     strcpy(bones, levels);
  600. }
  601.  
  602. /* Set names for bones[] and lock[] */
  603.  
  604. void
  605. set_lock_and_bones()
  606. {
  607.     if (!ramdisk) {
  608.         strcpy(levels, permbones);
  609.         strcpy(bones, permbones);
  610.     }
  611.     append_slash(permbones);
  612.     append_slash(levels);
  613.     append_slash(bones);
  614.     strcat(bones, allbones);
  615.     strcpy(lock, levels);
  616.     strcat(lock, alllevels);
  617. }
  618.  
  619. /*
  620.  * Add a slash to any name not ending in / or :.  There must
  621.  * be room for the /.
  622.  */
  623. void
  624. append_slash(name)
  625. char *name;
  626. {
  627.     char *ptr;
  628.  
  629.     if (!*name)
  630.         return;
  631.     ptr = name + (strlen(name) - 1);
  632.     if (*ptr != '/' && *ptr != ':') {
  633.         *++ptr = '/';
  634.         *++ptr = '\0';
  635.     }
  636. }
  637.  
  638.  
  639. void
  640. getreturn(str)
  641. char *str;
  642. {
  643.     int ch;
  644.  
  645.     msmsg("Hit <RETURN> %s.", str);
  646.     while ((ch = getchar()) != '\n')
  647.         ;
  648. }
  649.  
  650. void
  651. msmsg(fmt, a1, a2, a3)
  652. char *fmt;
  653. long a1, a2, a3;
  654. {
  655.     printf(fmt, a1, a2, a3);
  656.     (void) fflush(stdout);
  657. }
  658.  
  659. /* Follow the PATH, trying to fopen the file.
  660.  */
  661. #define PATHSEP    ';'
  662. #undef fopen
  663.  
  664. FILE *
  665. fopenp(name, mode)
  666. register char *name, *mode;
  667. {
  668.     char buf[BUFSIZ], *bp, *pp, lastch;
  669.     FILE *fp;
  670.     register struct FileLock *theLock;
  671.  
  672.     /* Try the default directory first.  Then look along PATH.
  673.      */
  674.     strcpy(buf, name);
  675.     if (theLock = Lock(buf, SHARED_LOCK)) {
  676.         UnLock(theLock);
  677.         if (fp = fopen(buf, mode))
  678.             return fp;
  679.     }
  680.     pp = PATH;
  681.     while (pp && *pp) {
  682.         bp = buf;
  683.         while (*pp && *pp != PATHSEP)
  684.             lastch = *bp++ = *pp++;
  685.         if (lastch != ':' && lastch != '/' && bp != buf)
  686.             *bp++ = '/';
  687.         strcpy(bp, name);
  688.         if (theLock = Lock(buf, SHARED_LOCK)) {
  689.             UnLock(theLock);
  690.             if (fp = fopen(buf, mode))
  691.                 return fp;
  692.         }
  693.         if (*pp)
  694.             pp++;
  695.     }
  696.     return NULL;
  697. }
  698. #endif /* DGK */
  699.  
  700. #ifdef CHDIR
  701.  
  702. /*
  703.  *  A not general-purpose directory changing routine.
  704.  *  Assumes you want to return to the original directory eventually,
  705.  *  by chdir()ing to orgdir.
  706.  *  Assumes -1 is not a valid lock, since 0 is valid.
  707.  */
  708.  
  709. #define NO_LOCK     ((struct FileLock *) -1)
  710.  
  711. char orgdir[1];
  712. static struct FileLock *OrgDirLock = NO_LOCK;
  713.  
  714. chdir(dir)
  715. char *dir;
  716. {
  717.     if (dir == orgdir) {
  718.         /* We want to go back to where we came from. */
  719.         if (OrgDirLock != NO_LOCK) {
  720.             UnLock(CurrentDir(OrgDirLock));
  721.             OrgDirLock = NO_LOCK;
  722.         }
  723.     } else {
  724.         /*
  725.          * Go to some new place. If still at the original
  726.          * directory, save the FileLock.
  727.          */
  728.         struct FileLock *newDir;
  729.  
  730.         if (newDir = Lock(dir, SHARED_LOCK)) {
  731.             if (OrgDirLock == NO_LOCK) {
  732.                 OrgDirLock = CurrentDir(newDir);
  733.             } else {
  734.                 UnLock(CurrentDir(newDir));
  735.             }
  736.         } else {
  737.             return -1;  /* Failed */
  738.         }
  739.     }
  740.     /* CurrentDir always succeeds if you have a lock */
  741.     return 0;
  742. }
  743.  
  744. #endif
  745.  
  746. /* Chdir back to original directory
  747.  */
  748. #undef exit
  749. void
  750. msexit(code)
  751. {
  752. #ifdef CHDIR
  753.     extern char orgdir[];
  754. #endif
  755.  
  756. #ifdef DGK
  757.     (void) fflush(stdout);
  758.     if (ramdisk)
  759.         copybones(TOPERM);
  760. #endif
  761. #ifdef CHDIR
  762.     chdir(orgdir);      /* chdir, not chdirx */
  763. #endif
  764.     /* Never know when exit is called... */
  765.     if (Initialized && (curx != 1 || cury != 1))
  766.         getret();
  767.  
  768.     CleanUp();
  769.     exit(code);
  770. }
  771.  
  772. /*
  773.  *  Strcmp while ignoring case. Not general-purpose, so static.
  774.  */
  775.  
  776. static int strcmpi(a, b)
  777. register char *a, *b;
  778. {
  779.     while (tolower(*a) == tolower(*b)) {
  780.         if (!*a)        /* *a == *b, so at end of both strings */
  781.             return 0;   /* equal. */
  782.         a++;
  783.         b++;
  784.     }
  785.     return 1;
  786. }
  787.  
  788. /*
  789.  *  cmpmem - used to compare two struct symbols, in lev.c
  790.  */
  791.  
  792. cmpmem(a, b, size)
  793. register unsigned char *a, *b;
  794. register int size;
  795. {
  796.     while (size--) {
  797.         if (*a++ != *b++)
  798.             return 1;   /* not equal */
  799.     }
  800.  
  801.     return 0;           /* equal */
  802. }
  803. SHAR_EOF
  804. cat << \SHAR_EOF > amigaMenu.c
  805. /*
  806.  *  amigaMenu.c     (C) Copyright 1988 by Olaf Seibert (KosmoSoft)
  807.  *
  808.  *  Originally by John Toebes.
  809.  */
  810.  
  811. #define TEXT(nam,str) \
  812. static struct IntuiText nam = {0,1,JAM2,0,0,NULL,(UBYTE *)str,NULL}
  813.  
  814.         /* Commands */
  815.         TEXT(T_HELP,  "?   display help");
  816.         TEXT(T_o,     "O   set options");
  817.         TEXT(T_SHELL, "!   AMIGADOS commands");
  818.         TEXT(T_v,     "v   version number");
  819.         TEXT(T_CR,    "^R  redraw screen");
  820.         TEXT(T_CP,    "^P  repeat last message");
  821.         TEXT(T_Q,     "Q   quit game");
  822.         TEXT(T_S,     "S   save the game");
  823.  
  824.         /* Inventory */
  825.         TEXT(T_i,     "i   inventory");
  826.         TEXT(T_p,     "p   pay your bill");
  827.         TEXT(T_d,     "d   drop an object");
  828.         TEXT(T_D,     "D   Drop several things");
  829.         TEXT(T_COMMA, ",   Pickup an object");
  830.         TEXT(T_SLASH, "/   identify something");
  831.         TEXT(T_c,     "c   call class of objects");
  832.         TEXT(T_C,     "C   Christen a monster");
  833.  
  834.         /* Actions */
  835.         TEXT(T_a,     "a   apply/use something");
  836.         TEXT(T_e,     "e   eat something");
  837.         TEXT(T_q,     "q   quaff a potion");
  838.         TEXT(T_r,     "r   read a scroll");
  839.         TEXT(T_t,     "t   throw/shoot weapon");
  840.         TEXT(T_z,     "z   zap a wand");
  841.  
  842.         /* Preparations */
  843.         TEXT(T_w,     "w   wield a weapon");
  844.         TEXT(T_P,     "P   Put on ring");
  845.         TEXT(T_R,     "R   Remove ring");
  846.         TEXT(T_T,     "T   Take off armor");
  847.         TEXT(T_W,     "W   Wear armor");
  848.         TEXT(T_WPN,   ")   current weapon");
  849.         TEXT(T_ARMOR, "[   current armor");
  850.         TEXT(T_RING,  "=   current rings");
  851.  
  852.         /* Movement */
  853.         TEXT(T_E,     "E   Engrave msg on floor");
  854.         TEXT(T_s,     "s   search");
  855.         TEXT(T_UP,    "<   Go up stairs");
  856.         TEXT(T_DOWN,  ">   Go down stairs");
  857.         TEXT(T_WAIT,  ".   wait a moment");
  858.         TEXT(T_CT,    "^T  Teleport");
  859.  
  860. #define IFLAGS ITEMENABLED|ITEMTEXT|HIGHCOMP
  861. #define IDATA(cmd,str,off) 0,off,WDT,9,IFLAGS,0,(APTR)&str,NULL,cmd,NULL,NULL
  862.  
  863. /* Commands */
  864.  
  865. #undef  WDT
  866. #define WDT 184
  867.  
  868. static struct MenuItem cmdsub[] = {
  869.     { &cmdsub[1], IDATA('?', T_HELP,   0) }, /*   display help */
  870.     { &cmdsub[2], IDATA('O', T_o,     10) }, /*   set options */
  871.     { &cmdsub[3], IDATA('!', T_SHELL, 20) }, /*   AMIGADOS commands */
  872.     { &cmdsub[4], IDATA('v', T_v,     30) }, /*   version number */
  873.     { &cmdsub[5], IDATA(022, T_CR,    40) }, /*R  redraw screen */
  874.     { &cmdsub[6], IDATA(024 ,T_CP,    50) }, /*P  repeat last message */
  875.     { &cmdsub[7], IDATA('Q', T_Q,     60) }, /*   quit game */
  876.     { NULL,       IDATA('S', T_S,     70) }  /*   save the game */
  877. };
  878.  
  879. /* Inventory */
  880.  
  881. #undef  WDT
  882. #define WDT 200
  883.  
  884. static struct MenuItem invsub[] = {
  885.     { &invsub[1], IDATA('i', T_i,      0) }, /*   inventory */
  886.     { &invsub[2], IDATA('p', T_p,     10) }, /*   pay your bill */
  887.     { &invsub[3], IDATA('d', T_d,     20) }, /*   drop an object */
  888.     { &invsub[4], IDATA('D', T_D,     30) }, /*   Drop several things */
  889.     { &invsub[5], IDATA(',', T_COMMA, 40) }, /*   Pickup an object */
  890.     { &invsub[6], IDATA('/', T_SLASH, 50) }, /*   identify something */
  891.     { &invsub[7], IDATA('c', T_c,     60) }, /*   call a class of objects */
  892.     { NULL,       IDATA('C', T_C,     70) }  /*   Christen a monster */
  893. };
  894.  
  895. /* Actions */
  896.  
  897. #undef  WDT
  898. #define WDT 184
  899.  
  900. static struct MenuItem actsub[] = {
  901.     { &actsub[1], IDATA('a', T_a,     0) }, /*   apply/use something */
  902.     { &actsub[2], IDATA('e', T_e,    10) }, /*   eat something */
  903.     { &actsub[3], IDATA('q', T_q,    20) }, /*   quaff a potion */
  904.     { &actsub[4], IDATA('r', T_r,    30) }, /*   read a scroll */
  905.     { &actsub[5], IDATA('t', T_t,    40) }, /*   throw/shoot weapon */
  906.     { NULL,       IDATA('z', T_z,    50) }  /*   zap a wand */
  907. };
  908.  
  909. /* Preparations */
  910.  
  911. #undef  WDT
  912. #define WDT 144
  913.  
  914. static struct MenuItem armsub[] = {
  915.     { &armsub[1], IDATA('w', T_w,      0) }, /*   wield a weapon */
  916.     { &armsub[2], IDATA('P', T_P,     10) }, /*   Put on ring */
  917.     { &armsub[3], IDATA('R', T_R,     20) }, /*   Remove ring */
  918.     { &armsub[4], IDATA('T', T_T,     30) }, /*   Take off armor */
  919.     { &armsub[5], IDATA('W', T_W,     40) }, /*   Wear armor */
  920.     { &armsub[6], IDATA(')', T_WPN,   50) }, /*   current weapon */
  921.     { &armsub[7], IDATA('[', T_ARMOR, 60) }, /*   current armor */
  922.     { NULL,       IDATA('=', T_RING,  70) }  /*   current rings */
  923. };
  924.  
  925. /* Movement */
  926.  
  927. #undef  WDT
  928. #define WDT 192
  929.  
  930. static struct MenuItem movsub[] = {
  931.     { &movsub[1], IDATA('E', T_E,     0) }, /*   Engrave msg on floor */
  932.     { &movsub[2], IDATA('s', T_s,    10) }, /*   search */
  933.     { &movsub[3], IDATA('<', T_UP,   20) }, /*   Go up stairs */
  934.     { &movsub[4], IDATA('>', T_DOWN, 30) }, /*   Go down stairs */
  935.     { &movsub[5], IDATA('.', T_WAIT, 40) }, /*   wait a moment */
  936.     { NULL,       IDATA(024, T_CT,   50) }  /*T  Teleport */
  937. };
  938.  
  939. /* Menustrip */
  940.  
  941. /* Width = #letters * 8 + 8 */
  942.  
  943. struct Menu HackMenu[] = {
  944.    { &HackMenu[1], 10,0, 72,0,MENUENABLED,"Commands",     &cmdsub[0] }, /*8*/
  945.    { &HackMenu[2], 82,0, 80,0,MENUENABLED,"Inventory",    &invsub[0] }, /*9*/
  946.    { &HackMenu[3],162,0, 64,0,MENUENABLED,"Actions",      &actsub[0] }, /*7*/
  947.    { &HackMenu[4],226,0,104,0,MENUENABLED,"Preparations", &armsub[0] }, /*12*/
  948.    { NULL,        330,0, 72,0,MENUENABLED,"Movement",     &movsub[0] }  /*8*/
  949. };
  950.  
  951. SHAR_EOF
  952. cat << \SHAR_EOF > amigaTTY.c
  953. /*    SCCS Id: @(#)amigaTTY.c    2.3    88/07/25
  954. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  955. /* tty.c - (Amiga) version */
  956.  
  957.  
  958. #include <stdio.h>
  959. #include "hack.h"
  960. #include "func_tab.h"
  961.  
  962. extern int Enable_Abort;
  963.  
  964. static char erase_char, kill_char;
  965.  
  966. /*
  967.  * Get initial state of terminal, set ospeed (for termcap routines)
  968.  * and switch off tab expansion if necessary.
  969.  * Called by startup() in termcap.c and after returning from ! or ^Z
  970.  */
  971. gettty()
  972. {
  973.     erase_char = 127;       /* DEL */
  974.     kill_char = 21;         /* cntl-U */
  975.     flags.cbreak = TRUE;
  976.     Enable_Abort = 0;
  977.     curx = 1;
  978.     cury = 1;
  979. }
  980.  
  981. /* reset terminal to original state */
  982. settty(s)
  983. char *s;
  984. {
  985.     end_screen();
  986.     if (s) {
  987.         printf(s);
  988.         curx = FAR;     /* For msexit(): don't exit immediately */
  989.     }
  990.     (void) fflush(stdout);
  991.     /* Do not close the screen, that is done in msexit() */
  992. }
  993.  
  994.  
  995. /* fatal error */
  996. /*VARARGS1*/
  997. error(s,x,y)
  998. char *s;
  999. {
  1000.     end_screen();
  1001.     putchar('\n');
  1002.     printf(s,x,y);
  1003.     putchar('\n');
  1004.     abort(1);
  1005. }
  1006.  
  1007. /*
  1008.  * Read a line closed with '\n' into the array char bufp[BUFSZ].
  1009.  * (The '\n' is not stored. The string is closed with a '\0'.)
  1010.  * Reading can be interrupted by an escape ('\033') - now the
  1011.  * resulting string is "\033".
  1012.  */
  1013. getlin(bufp)
  1014. register char *bufp;
  1015. {
  1016.     register char *obufp = bufp;
  1017.     register int c;
  1018.  
  1019.     flags.toplin = 2;        /* nonempty, no --More-- required */
  1020.     for(;;) {
  1021.         (void) fflush(stdout);
  1022.         if((c = getchar()) == EOF) {
  1023.             *bufp = 0;
  1024.             return;
  1025.         }
  1026.         if(c == '\033') {
  1027.             *obufp = c;
  1028.             obufp[1] = 0;
  1029.             return;
  1030.         }
  1031.         if(c == erase_char || c == '\b') {
  1032.             if(bufp != obufp) {
  1033.                 bufp--;
  1034.                 putstr("\b \b"); /* putsym converts \b */
  1035.             } else    bell();
  1036.         } else if(c == '\n') {
  1037.             *bufp = 0;
  1038.             return;
  1039.         } else if(' ' <= c && c < '\177') {
  1040.                 /* avoid isprint() - some people don't have it
  1041.                    ' ' is not always a printing char */
  1042.             *bufp = c;
  1043.             bufp[1] = 0;
  1044.             putstr(bufp);
  1045.             if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  1046.                 bufp++;
  1047.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  1048.                 /* this test last - @ might be the kill_char */
  1049.             while(bufp != obufp) {
  1050.                 bufp--;
  1051.                 putstr("\b \b");
  1052.             }
  1053.         } else
  1054.             bell();
  1055.     }
  1056. }
  1057.  
  1058. getret()
  1059. {
  1060.     cgetret("");
  1061. }
  1062.  
  1063. cgetret(s)
  1064. register char *s;
  1065. {
  1066.     putsym('\n');
  1067.     if(flags.standout)
  1068.         standoutbeg();
  1069.     putstr("Hit ");
  1070.     putstr(flags.cbreak ? "space" : "return");
  1071.     putstr(" to continue: ");
  1072.     if(flags.standout)
  1073.         standoutend();
  1074.     xwaitforspace(s);
  1075. }
  1076.  
  1077. char morc;    /* tell the outside world what char he used */
  1078.  
  1079. xwaitforspace(s)
  1080. register char *s;    /* chars allowed besides space or return */
  1081. {
  1082. register int c;
  1083.  
  1084.     morc = 0;
  1085.     while((c = readchar()) != '\n') {
  1086.         if(flags.cbreak) {
  1087.             if(c == ' ') break;
  1088.             if(s && index(s,c)) {
  1089.                 morc = c;
  1090.                 break;
  1091.             }
  1092.             bell();
  1093.         }
  1094.     }
  1095. }
  1096.  
  1097. static int last_multi;
  1098.  
  1099. char *
  1100. parse()
  1101. {
  1102.     static char inline[COLNO];
  1103.     register foo;
  1104.  
  1105.     flags.move = 1;
  1106.     if(!Invisible) curs_on_u(); else home();
  1107.     multi = 0;
  1108. #ifdef DGK
  1109.     while((foo = readchar()) >= '0' && foo <= '9') {
  1110.         multi = 10*multi+foo-'0';
  1111.         if (multi < 0 || multi > LARGEST_INT)
  1112.             multi = LARGEST_INT;
  1113.         if (multi > 9) {
  1114.             remember_topl();
  1115.             home();
  1116.             cl_end();
  1117.             printf("Count: %d", multi);
  1118.         }
  1119.         last_multi = multi;
  1120.     }
  1121. # ifdef REDO
  1122.     if (foo == DOAGAIN || in_doagain)
  1123.         multi = last_multi;
  1124.     else {
  1125.         savech(0);    /* reset input queue */
  1126.         savech(foo);
  1127.     }
  1128. # endif
  1129.  
  1130. #else /* DGK */
  1131.  
  1132.     while((foo = readchar()) >= '0' && foo <= '9')
  1133.         multi = 10*multi+foo-'0';
  1134.  
  1135. #endif /* DGK */
  1136.  
  1137.     if(multi) {
  1138.         multi--;
  1139.         save_cm = inline;
  1140.     }
  1141.     inline[0] = foo;
  1142.     inline[1] = 0;
  1143.     if(foo == 'g' || foo == 'G'){
  1144.         inline[1] = getchar();
  1145. #ifdef REDO
  1146.         savech(inline[1]);
  1147. #endif
  1148.         inline[2] = 0;
  1149.     }
  1150.     if(foo == 'm' || foo == 'M'){
  1151.         inline[1] = getchar();
  1152. #ifdef REDO
  1153.         savech(inline[1]);
  1154. #endif
  1155.         inline[2] = 0;
  1156.     }
  1157.     clrlin();
  1158.     return(inline);
  1159. }
  1160.  
  1161. char
  1162. readchar() {
  1163.     register int sym;
  1164.  
  1165.     (void) fflush(stdout);
  1166.     sym = getchar();
  1167.     if(flags.toplin == 1)
  1168.         flags.toplin = 2;
  1169.     return((char) sym);
  1170. }
  1171. #ifdef COM_COMPL
  1172. /* Read in an extended command - doing command line completion for
  1173.  * when enough character have been entered to make a unique command.
  1174.  * This is just a modified getlin().   -jsb
  1175.  */
  1176. get_ext_cmd(bufp)
  1177. register char *bufp;
  1178. {
  1179.     register char *obufp = bufp;
  1180.     register int c;
  1181.     int com_index, index;
  1182.  
  1183.     flags.toplin = 2;        /* nonempty, no --More-- required */
  1184.  
  1185.     for(;;) {
  1186.         (void) fflush(stdout);
  1187.         if((c = readchar()) == EOF) {
  1188.             *bufp = 0;
  1189.             return;
  1190.         }
  1191.         if(c == '\033') {
  1192.             *obufp = c;
  1193.             obufp[1] = 0;
  1194.             return;
  1195.         }
  1196.         if(c == erase_char || c == '\b') {
  1197.             if(bufp != obufp) {
  1198.                 bufp--;
  1199.                 putstr("\b \b"); /* putsym converts \b */
  1200.             } else    bell();
  1201.         } else if(c == '\n') {
  1202.             *bufp = 0;
  1203.             return;
  1204.         } else if(' ' <= c && c < '\177') {
  1205.                 /* avoid isprint() - some people don't have it
  1206.                    ' ' is not always a printing char */
  1207.             *bufp = c;
  1208.             bufp[1] = 0;
  1209.             index = 0;
  1210.             com_index = -1;
  1211.  
  1212.             while(extcmdlist[index].ef_txt != (char *) 0){
  1213.                 if(!strncmp(obufp, extcmdlist[index].ef_txt,
  1214.                 strlen(obufp)))
  1215.                     if(com_index == -1) /* No matches yet*/
  1216.                         com_index = index;
  1217.                     else /* More than 1 match */
  1218.                         com_index = -2;
  1219.                 index++;
  1220.             }
  1221.             if(com_index >= 0){
  1222.                 strcpy(obufp,
  1223.                 extcmdlist[com_index].ef_txt);
  1224.                 /* finish print our string */
  1225.                 putstr(bufp);
  1226.                 bufp = obufp; /* reset it */
  1227.                 if(strlen(obufp) < BUFSIZ-1 &&
  1228.                  strlen(obufp) < COLNO)
  1229.                     /* set bufp at the end of our
  1230.                      * string
  1231.                      */
  1232.                     bufp += strlen(obufp);
  1233.             } else {
  1234.                 putstr(bufp);
  1235.                 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  1236.                     bufp++;
  1237.             }
  1238.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  1239.                 /* this test last - @ might be the kill_char */
  1240.             while(bufp != obufp) {
  1241.                 bufp--;
  1242.                 putstr("\b \b");
  1243.             }
  1244.         } else
  1245.             bell();
  1246.     }
  1247.  
  1248. }
  1249. #endif COM_COMPL
  1250.  
  1251. SHAR_EOF
  1252. cat << \SHAR_EOF > amigaTermcap.c
  1253. /*    SCCS Id: @(#)termcap.c    2.1    87/10/19
  1254. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  1255.  
  1256. #include <stdio.h>
  1257. #include <ctype.h>    /* for isdigit() */
  1258. #include "hack.h"     /* for ROWNO, COLNO, *HI, *HE */
  1259.  
  1260. #define xputc(c)    WindowPutchar(c)
  1261. #define xputs(s)    WindowFPuts(s)
  1262.  
  1263. extern char *getenv();
  1264. extern long *alloc();
  1265.  
  1266. static char HO[] = "\x9BH";         /* Home */
  1267. static char CL[] = "\x1Bc";         /* Clear */
  1268. static char CE[] = "\x9BK";         /* Erase end of line */
  1269. static char UP[] = "\x0B";          /* Cursor up */
  1270. static char CM[] = "\x9B%d;%dH";    /* used with function tgoto() */
  1271. static char ND[] = "\x9BC";         /* Cursor right */
  1272. static char XD[] = "\x9BB";         /* Cursor down */
  1273. static char BC[] = "\x08";          /* Cursor left */
  1274.  
  1275. #ifdef MSDOSCOLOR    /* creps@silver.bacs.indiana.edu */
  1276. static char SO[] = "\x9B33m";       /* Standout: Color #3 (red) */
  1277. static char SE[] = "\x9B0m";
  1278.  
  1279. #else
  1280.  
  1281. static char SO[] = "\x9B7m";        /* Inverse video */
  1282. static char SE[] = "\x9B0m";
  1283. #endif
  1284.  
  1285. char *CD = "\x9BJ"; /* char *CD; tested in pri.c: docorner() */
  1286.  
  1287. /* #if defined(DGK) || defined(SORTING) */
  1288. #ifdef DGK
  1289. # define XXX
  1290. #endif
  1291. #ifdef SORTING
  1292. # define XXX
  1293. #endif
  1294.  
  1295. #ifdef XXX
  1296. # ifdef MSDOSCOLOR
  1297. char *HI_OBJ = "\x9B31;42m";        /* White on Black */
  1298. char *HI_MON = "\x9B33;42m";        /* Orange on black */
  1299. char *HI = "\x9B1m";                /* Bold (hilight) */
  1300. char *HE = "\x9B0m";                /* Plain */
  1301. # else
  1302. char *HI_OBJ = "";
  1303. char *HI_MON = "";
  1304. char *HI = "\x9B4m";                /* Underline */
  1305. char *HE = "\x9B0m";                /* Plain */
  1306. # endif
  1307. #endif
  1308. #undef XXX
  1309.  
  1310. int CO = COLNO;
  1311. int LI = ROWNO;         /* used in pri.c and whatis.c */
  1312.  
  1313. static char tgotobuf[20];
  1314. #define tgoto(fmt, x, y)    (sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
  1315.  
  1316. startup()
  1317. {
  1318.     (void) Initialize();    /* This opens screen, window, console, &c */
  1319. }
  1320.  
  1321. start_screen()
  1322. {
  1323. }
  1324.  
  1325. end_screen()
  1326. {
  1327.     clear_screen();
  1328. }
  1329.  
  1330. /* Cursor movements */
  1331. extern xchar curx, cury;
  1332.  
  1333. #ifdef TERMCAP
  1334.  
  1335. curs(x, y)
  1336. register int x, y;    /* not xchar: perhaps xchar is unsigned and
  1337.                curx-x would be unsigned as well */
  1338. {
  1339.  
  1340.     if (y == cury && x == curx)
  1341.         return;
  1342.     if(!ND && (curx != x || x <= 3)) {    /* Extremely primitive */
  1343.         cmov(x, y);            /* bunker!wtm */
  1344.         return;
  1345.     }
  1346.     if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
  1347.         nocmov(x, y);
  1348.     else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
  1349.         (void) putchar('\r');
  1350.         curx = 1;
  1351.         nocmov(x, y);
  1352.     } else if(!CM) {
  1353.         nocmov(x, y);
  1354.     } else
  1355.         cmov(x, y);
  1356. }
  1357.  
  1358. nocmov(x, y)
  1359. {
  1360.     if (cury > y) {
  1361.         if(UP) {
  1362.             while (cury > y) {    /* Go up. */
  1363.                 xputs(UP);
  1364.                 cury--;
  1365.             }
  1366.         } else if(CM) {
  1367.             cmov(x, y);
  1368.         } else if(HO) {
  1369.             home();
  1370.             curs(x, y);
  1371.         } /* else impossible("..."); */
  1372.     } else if (cury < y) {
  1373.         if(XD) {
  1374.             while(cury < y) {
  1375.                 xputs(XD);
  1376.                 cury++;
  1377.             }
  1378.         } else if(CM) {
  1379.             cmov(x, y);
  1380.         } else {
  1381.             while(cury < y) {
  1382.                 xputc('\n');
  1383.                 curx = 1;
  1384.                 cury++;
  1385.             }
  1386.         }
  1387.     }
  1388.     if (curx < x) {        /* Go to the right. */
  1389.         if(!ND) cmov(x, y); else    /* bah */
  1390.             /* should instead print what is there already */
  1391.         while (curx < x) {
  1392.             xputs(ND);
  1393.             curx++;
  1394.         }
  1395.     } else if (curx > x) {
  1396.         while (curx > x) {    /* Go to the left. */
  1397.             xputs(BC);
  1398.             curx--;
  1399.         }
  1400.     }
  1401. }
  1402.  
  1403. cmov(x, y)
  1404. register x, y;
  1405. {
  1406.     xputs(tgoto(CM, x-1, y-1));
  1407.     cury = y;
  1408.     curx = x;
  1409. }
  1410.  
  1411. #else /* !TERMCAP */
  1412.  
  1413. curs(x, y)
  1414. register x, y;
  1415. {
  1416.     if (x != curx || y != cury) {
  1417.         xputs(tgoto(CM, x-1, y-1));
  1418.         cury = y;
  1419.         curx = x;
  1420.     }
  1421. }
  1422. #endif /* TERMCAP */
  1423.  
  1424. #ifndef xputc
  1425. xputc(c) char c; {
  1426.     (void) putchar(c, stdout);
  1427. }
  1428. #endif
  1429.  
  1430. #ifndef xputs
  1431. xputs(s) char *s; {
  1432.     WindowFPuts(s);
  1433. }
  1434. #endif
  1435.  
  1436. cl_end() {
  1437. #ifdef TERMCAP
  1438.     if(CE)
  1439.         xputs(CE);
  1440.     else {    /* no-CE fix - free after Harold Rynes */
  1441.         /* this looks terrible, especially on a slow terminal
  1442.            but is better than nothing */
  1443.         register cx = curx, cy = cury;
  1444.  
  1445.         while(curx < COLNO) {
  1446.             xputc(' ');
  1447.             curx++;
  1448.         }
  1449.         curs(cx, cy);
  1450.     }
  1451. #else
  1452.     xputs(CE);
  1453. #endif
  1454. }
  1455.  
  1456. clear_screen() {
  1457.     xputs(CL);
  1458.     home();
  1459. }
  1460.  
  1461. home()
  1462. {
  1463. #ifdef TERMCAP
  1464.     if(HO)
  1465.         xputs(HO);
  1466.     else if(CM)
  1467.         xputs(tgoto(CM, 0, 0));
  1468.     else
  1469.         curs(1, 1);    /* using UP ... */
  1470. #else
  1471.     xputs(HO);
  1472. #endif
  1473.     curx = cury = 1;
  1474. }
  1475.  
  1476. standoutbeg()
  1477. {
  1478. #ifdef TERMCAP
  1479.     if(SO)
  1480. #endif
  1481.         xputs(SO);
  1482. }
  1483.  
  1484. standoutend()
  1485. {
  1486. #ifdef TERMCAP
  1487.     if(SE)
  1488. #endif
  1489.         xputs(SE);
  1490. }
  1491.  
  1492. backsp()
  1493. {
  1494.     xputs(BC);
  1495.     curx--;
  1496. }
  1497.  
  1498. bell()
  1499. {
  1500. #ifdef DGKMOD
  1501.     if (flags.silent) return;
  1502. #endif /* DGKMOD /**/
  1503.     (void) putchar('\007');        /* curx does not change */
  1504.     (void) fflush(stdout);
  1505. }
  1506.  
  1507. delay_output() {
  1508.     /* delay 50 ms - could also use a 'nap'-system call */
  1509.     Delay(2L);
  1510. }
  1511.  
  1512. cl_eos()            /* free after Robert Viduya */
  1513. {                /* must only be called with curx = 1 */
  1514. #ifdef TERMCAP
  1515.     if(CD)
  1516.         xputs(CD);
  1517.     else {
  1518.         register int cx = curx, cy = cury;
  1519.         while(cury <= LI-2) {
  1520.             cl_end();
  1521.             xputc('\n');
  1522.             curx = 1;
  1523.             cury++;
  1524.         }
  1525.         cl_end();
  1526.         curs(cx, cy);
  1527.     }
  1528. #else
  1529.     xputs(CD);
  1530. #endif
  1531. }
  1532.  
  1533. SHAR_EOF
  1534. cat << \SHAR_EOF > amigaUnix.c
  1535. /*    SCCS Id: @(#)pcunix.c    1.4    87/08/08
  1536. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  1537. /* unix.c - version 1.0.3 */
  1538.  
  1539. /* This file collects some Unix dependencies; pager.c contains some more */
  1540.  
  1541. /*
  1542.  * The time is used for:
  1543.  *    - seed for rand()
  1544.  *    - year on tombstone and yymmdd in record file
  1545.  *    - phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
  1546.  *    - night and midnight (the undead are dangerous at midnight)
  1547.  *    - determination of what files are "very old"
  1548.  */
  1549.  
  1550. #include <stdio.h>    /* mainly for NULL */
  1551. #include "hack.h"    /* mainly for index() which depends on BSD */
  1552.  
  1553. #include    <time.h>
  1554. #include    <stat.h>
  1555.  
  1556. extern time_t time();
  1557. static struct stat buf, hbuf;
  1558.  
  1559. setrandom()
  1560. {
  1561.     (void) srand((int) time ((time_t *) 0));
  1562. }
  1563.  
  1564. struct tm *
  1565. getlt()
  1566. {
  1567.     time_t date;
  1568.     struct tm *localtime();
  1569.  
  1570.     (void) time(&date);
  1571.     return(localtime(&date));
  1572. }
  1573.  
  1574. getyear()
  1575. {
  1576.     return(1900 + getlt()->tm_year);
  1577. }
  1578.  
  1579. char *
  1580. getdate()
  1581. {
  1582.     static char datestr[7];
  1583.     register struct tm *lt = getlt();
  1584.  
  1585.     (void) sprintf(datestr, "%2d%2d%2d",
  1586.         lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
  1587.     if(datestr[2] == ' ') datestr[2] = '0';
  1588.     if(datestr[4] == ' ') datestr[4] = '0';
  1589.     return(datestr);
  1590. }
  1591.  
  1592. phase_of_the_moon()            /* 0-7, with 0: new, 4: full */
  1593. {                    /* moon period: 29.5306 days */
  1594.                     /* year: 365.2422 days */
  1595.     register struct tm *lt = getlt();
  1596.     register int epact, diy, golden;
  1597.  
  1598.     diy = lt->tm_yday;
  1599.     golden = (lt->tm_year % 19) + 1;
  1600.     epact = (11 * golden + 18) % 30;
  1601.     if ((epact == 25 && golden > 11) || epact == 24)
  1602.         epact++;
  1603.  
  1604.     return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 );
  1605. }
  1606.  
  1607. night()
  1608. {
  1609.     register int hour = getlt()->tm_hour;
  1610.  
  1611.     return(hour < 6 || hour > 21);
  1612. }
  1613.  
  1614. midnight()
  1615. {
  1616.     return(getlt()->tm_hour == 0);
  1617. }
  1618.  
  1619. gethdate(name) char *name; {
  1620. /* old version - for people short of space */
  1621. /*
  1622. /* register char *np;
  1623. /*      if(stat(name, &hbuf))
  1624. /*              error("Cannot get status of %s.",
  1625. /*                      (np = rindex(name, '/')) ? np+1 : name);
  1626. /*
  1627. /* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */
  1628.  
  1629. /*
  1630.  * The problem with   #include  <sys/param.h> is that this include file
  1631.  * does not exist on all systems, and moreover, that it sometimes includes
  1632.  * <sys/types.h> again, so that the compiler sees these typedefs twice.
  1633.  */
  1634. #define         MAXPATHLEN      80
  1635.  
  1636. extern char PATH[];     /* In amigaDOS.c */
  1637.  
  1638. register char *np, *path;
  1639. char filename[MAXPATHLEN+1];
  1640.  
  1641.     if (index(name, '/') != NULL || (path = PATH) == NULL)
  1642.         path = "";
  1643.  
  1644.     for (;;) {
  1645.         if ((np = index(path, ':')) == NULL)
  1646.             np = path + strlen(path);       /* point to end str */
  1647.         if (np - path <= 1)                     /* %% */
  1648.             (void) strcpy(filename, name);
  1649.         else {
  1650.             (void) strncpy(filename, path, np - path);
  1651.             filename[np - path] = '/';
  1652.             (void) strcpy(filename + (np - path) + 1, name);
  1653.         }
  1654.         if (stat(filename, &hbuf) == 0)
  1655.             return;
  1656.         if (*np == '\0')
  1657.         path = "";
  1658.         path = np + 1;
  1659.     }
  1660.     error("Cannot get status of %s.", (np = rindex(name, '/')) ? np+1 : name);
  1661. }
  1662.  
  1663. uptodate(fd) {
  1664. #ifndef AMIGA   /* Amiga has no fstat */
  1665.     if(fstat(fd, &buf)) {
  1666.         pline("Cannot get status of saved level? ");
  1667.         return(0);
  1668.     }
  1669.     if(buf.st_mtime < hbuf.st_mtime) {
  1670.         pline("Saved level is out of date. ");
  1671.         return(0);
  1672.     }
  1673. #endif
  1674.     return(1);
  1675. }
  1676.  
  1677. regularize(s)    /* normalize file name - we don't like :'s or /'s */
  1678. register char *s;
  1679. {
  1680.     register char *lp;
  1681.  
  1682.     while((lp = index(s, ':')) || (lp = index(s, '/')))
  1683.         *lp = '_';
  1684. }
  1685. SHAR_EOF
  1686. cat << \SHAR_EOF > amigaWindow.c
  1687. /*
  1688.  *  amigaWindow.c   (C) Copyright 1988 by Olaf Seibert (KosmoSoft)
  1689.  */
  1690.  
  1691. /*
  1692.  *  Here is some very Amiga specific stuff, dealing with
  1693.  *  screens, windows and menus.
  1694.  */
  1695.  
  1696. #include "config.h"
  1697.  
  1698. #define HACKFONT
  1699.  
  1700. #undef TRUE
  1701. #undef FALSE
  1702. #undef COUNT
  1703.  
  1704. #include <exec/types.h>
  1705. #include <exec/alerts.h>
  1706. #include <exec/io.h>
  1707. #include <exec/devices.h>
  1708. #include <devices/console.h>
  1709. #include <intuition/intuition.h>
  1710. #include <libraries/dosextens.h>
  1711.  
  1712. #include "amigaMenu.c"
  1713.  
  1714. /*  First, external declarations... */
  1715.  
  1716. struct Library *OpenLibrary();
  1717. struct Screen *OpenScreen();
  1718. struct Window *OpenWindow();
  1719. struct TextFont *OpenDiskFont();
  1720. struct IntuiMessage *GetMsg();
  1721. struct MenuItem *ItemAddress();
  1722. struct Process *FindTask();         /* Cheating */
  1723. long DeadKeyConvert(), OpenDevice(), CloseDevice();
  1724. extern struct Library *IconBase;
  1725.  
  1726. /*  Now our own variables */
  1727.  
  1728. struct Library *IntuitionBase;
  1729. struct Screen *HackScreen;
  1730. struct Window *HackWindow;
  1731. struct Window *pr_WindowPtr;
  1732. struct IOStdReq ConsoleIO;
  1733. char Initialized = FALSE;
  1734.  
  1735. #ifdef HACKFONT
  1736. struct Library *GfxBase;
  1737. struct Library *DiskfontBase;
  1738. #endif
  1739.  
  1740. struct Device *ConsoleDevice;
  1741.  
  1742. #define CSI         '\x9b'
  1743. #define NO_CHAR     -1
  1744. #define RAWHELP     0x5F        /* Rawkey code of the HELP key */
  1745.  
  1746. /*
  1747.  *  It is assumed that all multiple-character outputs are
  1748.  *  at most CONBUFFER characters each.
  1749.  */
  1750.  
  1751. #define CONBUFFER   BUFSZ               /* 512 */
  1752. static char ConsoleBuffer[CONBUFFER];
  1753. static unsigned short Buffered;
  1754.  
  1755. #define KBDBUFFER   10
  1756. static unsigned char KbdBuffer[KBDBUFFER];
  1757. static unsigned char KbdBuffered;
  1758.  
  1759. #define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = ch)
  1760.  
  1761. /*
  1762.  *  It seems Intuition won't OpenDiskFont our diskFont, so we get the
  1763.  *  closest match, which is of course topaz/8. (and if not, it is still
  1764.  *  an 8-pixel font, so everything still looks ok)
  1765.  */
  1766.  
  1767. struct TextAttr Hack80 = {
  1768. #ifdef HACKFONT
  1769.     (UBYTE *) "NetHack:Hack.font",
  1770. #else
  1771.     (UBYTE *) "topaz.font",
  1772. #endif
  1773.     TOPAZ_EIGHTY, FS_NORMAL, FPF_DISKFONT
  1774. };
  1775.  
  1776. #ifdef HACKFONT
  1777. struct TextFont *HackFont;
  1778. #endif
  1779.  
  1780. #define BARHEIGHT       11
  1781. #define WINDOWHEIGHT    192
  1782. #define WIDTH           640
  1783. #define DEPTH           2
  1784.  
  1785. struct NewScreen NewHackScreen = {
  1786.     0, 0, WIDTH, BARHEIGHT + WINDOWHEIGHT, DEPTH,
  1787.     0, 1,     /* DetailPen, BlockPen */
  1788.     HIRES,
  1789.     CUSTOMSCREEN,
  1790.     &Hack80,  /* Font */
  1791.     (UBYTE *) "NetHack 2.3 - Ported by Olaf Seibert (KosmoSoft)",
  1792.     NULL,     /* Gadgets */
  1793.     NULL,     /* CustomBitmap */
  1794. };
  1795.  
  1796. struct NewWindow NewHackWindow = {
  1797.     /* left, top, width, height, detailpen, blockpen */
  1798.     0, BARHEIGHT, WIDTH, WINDOWHEIGHT, -1, -1,
  1799.     RAWKEY | MENUPICK /* | MOUSEBUTTONS | GADGETDOWN */ ,
  1800.     BORDERLESS | BACKDROP | ACTIVATE,
  1801.     NULL, NULL, NULL,
  1802.     NULL, NULL, -1,-1,-1,-1, CUSTOMSCREEN
  1803. };
  1804.  
  1805. static int BufferGetchar()
  1806. {
  1807.     register unsigned char *from, *to;
  1808.     register int c;
  1809.     register short i;
  1810.  
  1811.     if (KbdBuffered) {
  1812.         c = KbdBuffer[0];
  1813.         KbdBuffered--;
  1814.         to = KbdBuffer;
  1815.         from = to + 1;
  1816.         /* Move the remaining characters */
  1817.         for (i = KbdBuffered; i > 0; i--) {
  1818.             *to++ = *from++;
  1819.         }
  1820.         return c;
  1821.     }
  1822.  
  1823.     return NO_CHAR;
  1824. }
  1825.  
  1826. /*
  1827.  *  This should remind you remotely of DeadKeyConvert,
  1828.  *  but we are cheating a bit.
  1829.  *  We want complete control over the numeric keypad, and no
  1830.  *  dead keys... (they are assumed to be on Alted keys)
  1831.  *  Also assumed is that the IntuiMessage is of type RAWKEY.
  1832.  *  For some reason, IECODE_UP_PREFIX events seem to be lost when they
  1833.  *  occur while our console window is inactive. This is particulary
  1834.  *  troublesome with qualifier keys... Is this because I never
  1835.  *  RawKeyConvert those events???
  1836.  */
  1837.  
  1838. int ConvertKey(message)
  1839. register struct IntuiMessage *message;
  1840. {
  1841.     static struct InputEvent theEvent;
  1842.     static char       numpad[] = "bjnh.lyku";
  1843.     static char  ctrl_numpad[] = "\x02\x0A\x0E\x08.\x0C\x19\x0B\x15";
  1844.     static char shift_numpad[] = "BJNH.LYKU";
  1845.  
  1846.     unsigned char buffer[1];
  1847.     register char length;
  1848.     register ULONG qualifier = message->Qualifier;
  1849.     char numeric_pad, shift, control, alt;
  1850.  
  1851.     control = (qualifier &  IEQUALIFIER_CONTROL) != 0;
  1852.     shift   = (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0;
  1853.  
  1854.     /*
  1855.      *  Shortcut for HELP and arrow keys... I suppose this is allowed...
  1856.      *  the defines are in intuition/intuition.h, and the keys
  1857.      *  don't serve 'text' input, normally.
  1858.      *  Also, parsing their escape sequences is such a mess...
  1859.      */
  1860.  
  1861.     switch (message->Code) {
  1862.     case RAWHELP:
  1863.         length = '?';
  1864.         goto no_arrow;
  1865.     case CURSORLEFT:
  1866.         length = 'h'; goto arrow;
  1867.     case CURSORDOWN:
  1868.         length = 'j'; goto arrow;
  1869.     case CURSORUP:
  1870.         length = 'k'; goto arrow;
  1871.     case CURSORRIGHT:
  1872.         length = 'l';
  1873.     arrow:
  1874.         if (control)
  1875.             length &= 0x1F;         /* ToControl... */
  1876.         else if (shift)
  1877.             length &= 0x5F;         /* ToUpper... */
  1878.     no_arrow:
  1879.         BufferQueueChar(length);
  1880.         return;
  1881.     }
  1882.  
  1883. #ifdef BETA
  1884.     if (!ConsoleDevice) { /* Should never happen */
  1885.         abort(AG_IOError | AO_ConsoleDev);
  1886.         return;
  1887.     }
  1888. #endif
  1889.  
  1890.     numeric_pad = (qualifier & IEQUALIFIER_NUMERICPAD) != 0;
  1891.     if (alt = (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) != 0)
  1892.                 /* Don't want dead keys... */
  1893.         qualifier &= ~(IEQUALIFIER_LALT | IEQUALIFIER_RALT);
  1894.  
  1895.     theEvent.ie_Class = IECLASS_RAWKEY;
  1896.     theEvent.ie_Code = message->Code;
  1897.     theEvent.ie_Qualifier = numeric_pad ? IEQUALIFIER_NUMERICPAD :
  1898.                                           qualifier;
  1899.     theEvent.ie_EventAddress = (APTR) *(message->IAddress);
  1900.  
  1901.     length = RawKeyConvert(&theEvent, buffer, (long) sizeof(buffer), NULL);
  1902.  
  1903.     if (length == 1) {   /* Plain ASCII character */
  1904.         length = buffer[0];
  1905.         if (numeric_pad && length >= '1' && length <= '9') {
  1906.             length -= '1';
  1907.             if (control) {
  1908.                 length = ctrl_numpad[length];
  1909.             } else if (shift) {
  1910.                 length = shift_numpad[length];
  1911.             } else {
  1912.                 length = numpad[length];
  1913.             }
  1914.         }
  1915.         BufferQueueChar(length);
  1916.     } /* else shift, ctrl, alt, amiga, F-key, shift-tab, etc */
  1917. }
  1918. /*
  1919.  *  Process an incoming IntuiMessage.
  1920.  *  It would certainly look nicer if this could be done using a
  1921.  *  PA_SOFTINT message port, but we cannot call RawKeyConvert()
  1922.  *  during a software interrupt.
  1923.  *  Anyway, kbhit() is called often enough, and usually gets
  1924.  *  ahead of input demands, when the user types ahead.
  1925.  */
  1926.  
  1927. static char ProcessMessage(message)
  1928. register struct IntuiMessage *message;
  1929. {
  1930.     switch(message->Class) {
  1931.     case MENUPICK:
  1932.         {
  1933.             USHORT thismenu;
  1934.             struct MenuItem *item = NULL;
  1935.  
  1936.             thismenu = message->Code;
  1937.             while (thismenu != MENUNULL) {
  1938.                 item = ItemAddress(&HackMenu, (ULONG) thismenu);
  1939.                 if (KbdBuffered < KBDBUFFER)
  1940.                     BufferQueueChar(item->Command); /* Unused: No COMMSEQ */
  1941.                 thismenu = item->NextSelect;
  1942.             }
  1943.         }
  1944.         break;
  1945.     case RAWKEY:
  1946.         if (!(message->Code & IECODE_UP_PREFIX))
  1947.             ConvertKey(message);    /* May queue multiple characters */
  1948.         break;                      /* but doesn't do that yet       */
  1949. #if 0
  1950.     case CLOSEWINDOW:
  1951.         BufferQueueChar('Q');
  1952.         break;
  1953. #endif
  1954. #if 0
  1955.     case GADGETDOWN:
  1956.         BufferQueueChar( ((struct Gadget *)message->IAddress)->GadgetID );
  1957.         break;
  1958. #endif
  1959.     }
  1960.     ReplyMsg(message);
  1961. }
  1962.  
  1963. /*
  1964.  *  Get all incoming messages and fill up the keyboard buffer,
  1965.  *  thus allowing Intuition to (maybe) free up the IntuiMessages.
  1966.  *  Return when no more messages left, or keyboard buffer half full.
  1967.  *  We need to do this since there is no one-to-one correspondence
  1968.  *  between characters and incoming messages.
  1969.  */
  1970.  
  1971. int kbhit()
  1972. {
  1973.     register struct IntuiMessage *message;
  1974.  
  1975.     while( (KbdBuffered < KBDBUFFER / 2) &&
  1976.             (message = GetMsg(HackWindow->UserPort)) )
  1977.         ProcessMessage(message);
  1978.  
  1979.     return KbdBuffered;
  1980. }
  1981.  
  1982. /*
  1983.  *  Get a character from the keyboard buffer, waiting if
  1984.  *  not available.
  1985.  */
  1986.  
  1987. int WindowGetchar()
  1988. {
  1989.     while ( !kbhit() ) {
  1990.         Wait( 1L << HackWindow->UserPort->mp_SigBit );
  1991.     }
  1992.     return BufferGetchar();
  1993. }
  1994.  
  1995. /*
  1996.  *  Flush the output waiting in the console output buffer.
  1997.  */
  1998.  
  1999. void WindowFlush()
  2000. {
  2001. #ifdef BETA
  2002.     if (!ConsoleDevice) { /* Should never happen */
  2003.         abort(AG_IOError | AO_ConsoleDev);
  2004.         return;
  2005.     }
  2006. #endif
  2007.  
  2008.     if (Buffered) {
  2009.         ConsoleIO.io_Command = CMD_WRITE;
  2010.         ConsoleIO.io_Data = (APTR)ConsoleBuffer;
  2011.         ConsoleIO.io_Length = Buffered;
  2012.         DoIO(&ConsoleIO);
  2013.         Buffered = 0;
  2014.     }
  2015. }
  2016.  
  2017. /*
  2018.  *  Queue a single character for output to the console screen.
  2019.  */
  2020.  
  2021. int WindowPutchar(c)
  2022. char c;
  2023. {
  2024.     if (Buffered >= CONBUFFER)
  2025.         WindowFlush();
  2026.  
  2027.     ConsoleBuffer[Buffered++] = c;
  2028. }
  2029.  
  2030. /*
  2031.  *  Queue an entire string for output to the console screen,
  2032.  *  flushing the existing characters first, if necessary.
  2033.  *  Do not append a newline.
  2034.  */
  2035.  
  2036. void WindowFPuts(string)
  2037. char *string;
  2038. {
  2039.     register int len = _BUILTIN_strlen(string);
  2040.  
  2041.     if (len + Buffered >= CONBUFFER)
  2042.         WindowFlush();
  2043.  
  2044.     _BUILTIN_strcpy(ConsoleBuffer + Buffered, string);
  2045.     Buffered += len;
  2046. }
  2047.  
  2048. /*
  2049.  *  Queue an entire string for output to the console screen,
  2050.  *  flushing the existing characters first, if necessary.
  2051.  *  Append a newline.
  2052.  */
  2053.  
  2054. void WindowPuts(string)
  2055. char *string;
  2056. {
  2057.     WindowFPuts(string);
  2058.     WindowPutchar('\n');
  2059. }
  2060.  
  2061. /*
  2062.  *  Queue a formatted string for output to the console screen,
  2063.  *  flushing the existing characters first, if necessary.
  2064.  */
  2065.  
  2066. void WindowPrintf(fmt, args, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
  2067. char *fmt;
  2068. long args, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9;
  2069. {
  2070. #ifdef AZTEC_C      /* Efficient but not portable */
  2071.     format(WindowPutchar, fmt, &args);
  2072. #else
  2073.     WindowFlush();  /* Don't know if all will fit */
  2074. # ifdef __STDC__    /* Cheap and portable way */
  2075.     vsprintf(ConsoleBuffer, fmt, &args);
  2076. # else              /* Expensive... */
  2077.     sprintf(ConsoleBuffer, fmt, args, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
  2078. arg9);
  2079. # endif
  2080.     ConsoleIO.io_Command = CMD_WRITE;
  2081.     ConsoleIO.io_Data = (APTR)ConsoleBuffer;
  2082.     ConsoleIO.io_Length = -1;
  2083.     DoIO(&ConsoleIO);
  2084. #endif
  2085. }
  2086.  
  2087. void CleanUp()
  2088. {
  2089.     struct IntuiMessage *msg;
  2090.  
  2091.     /* Clean up resources */
  2092.  
  2093.     if (ConsoleIO.io_Device) {
  2094.         CloseDevice(&ConsoleIO);
  2095.         ConsoleDevice = NULL;
  2096.     }
  2097.     if (HackWindow) {
  2098.         FindTask(NULL)->pr_WindowPtr = (APTR) pr_WindowPtr;
  2099.         ClearMenuStrip(HackWindow);
  2100.         Forbid();
  2101.         while (msg = GetMsg(HackWindow->UserPort))
  2102.             ReplyMsg(msg);
  2103.         CloseWindow(HackWindow);
  2104.         Permit();
  2105.         HackWindow = NULL;
  2106.     }
  2107.     if (HackScreen) {
  2108.         CloseScreen(HackScreen);
  2109.         HackScreen = NULL;
  2110.     }
  2111.     /* if (IconBase) {
  2112.         CloseLibrary(IconBase);
  2113.         IconBase = NULL;
  2114.     } */
  2115. #ifdef HACKFONT
  2116.     if (HackFont) {
  2117.         CloseFont(HackFont);
  2118.         HackFont = NULL;
  2119.     }
  2120.     if (DiskfontBase) {
  2121.         CloseLibrary(DiskfontBase);
  2122.         DiskfontBase = NULL;
  2123.     }
  2124.     if (GfxBase) {
  2125.         CloseLibrary(GfxBase);
  2126.         GfxBase = NULL;
  2127.     }
  2128. #endif
  2129.     if (IntuitionBase) {
  2130.         CloseLibrary(IntuitionBase);
  2131.         IntuitionBase = NULL;
  2132.     }
  2133.  
  2134.     Initialized = FALSE;
  2135. }
  2136.  
  2137. void abort(rc)
  2138. long rc;
  2139. {
  2140. #ifdef CHDIR
  2141.     extern char orgdir[];
  2142.     chdir(orgdir);
  2143. #endif
  2144.     if (Initialized && ConsoleDevice) {
  2145.         printf("\n\nAbort with alert code %08lx...\n", rc);
  2146.         getret();
  2147.     } else
  2148.         Alert(rc, 0L);
  2149.     CleanUp();
  2150. #undef exit
  2151.     exit(rc);
  2152. }
  2153.  
  2154. /*  Used by library routines, and the debugger */
  2155.  
  2156. void _abort()
  2157. {
  2158.     abort(-10L);
  2159. }
  2160.  
  2161. /*
  2162.  *  Open everything we need.
  2163.  */
  2164.  
  2165. void Initialize()
  2166. {
  2167.     if (Initialized)
  2168.         return;
  2169.  
  2170.     if ( (IntuitionBase = OpenLibrary("intuition.library", LIBRARY_VERSION))
  2171.           == NULL)
  2172.         abort(AG_OpenLib | AO_Intuition);
  2173.  
  2174. #ifdef HACKFONT
  2175.  
  2176.     if ( (GfxBase = OpenLibrary("graphics.library",LIBRARY_VERSION)) == NULL)
  2177.         abort(AG_OpenLib | AO_GraphicsLib);
  2178.  
  2179.     /*
  2180.      *  Force our own font to be loaded, if possible.
  2181.      *  If we can open diskfont.library, but not our font, we can close
  2182.      *  the diskfont.library again since it just wastes memory.
  2183.      *  Even if we can open the font, we don't need the diskfont.library
  2184.      *  anymore, since CloseFont is a graphics.library function.
  2185.      */
  2186.  
  2187.     if (DiskfontBase = OpenLibrary("diskfont.library", LIBRARY_VERSION)) {
  2188.         HackFont = OpenDiskFont(&Hack80);
  2189.         CloseLibrary(DiskfontBase);
  2190.         DiskfontBase = NULL;
  2191.     }
  2192. #endif
  2193.  
  2194.     /* if ( (IconBase = OpenLibrary("icon.library",LIBRARY_VERSION)) == NULL)
  2195.         abort(AG_OpenLib | AO_IconLib); */
  2196.  
  2197.     /*
  2198.      *  Now Intuition is supposed to use our HackFont for the screen,
  2199.      *  since we have a corresponding TextAttr, but it *doesn't*.
  2200.      *  So, we need to do a SetFont() a bit later on.
  2201.      */
  2202.     if ( (HackScreen = OpenScreen(&NewHackScreen)) == NULL)
  2203.         abort(AN_OpenScreen & ~AT_DeadEnd);
  2204.  
  2205.     NewHackWindow.Screen = HackScreen;
  2206.  
  2207.     if ( (HackWindow = OpenWindow(&NewHackWindow)) == NULL)
  2208.         abort(AN_OpenWindow & ~AT_DeadEnd);
  2209.  
  2210.     SetMenuStrip(HackWindow,&HackMenu);
  2211.     {
  2212.         register struct Process *myProcess = FindTask(NULL);
  2213.         pr_WindowPtr = (struct Window *)myProcess->pr_WindowPtr;
  2214.         myProcess->pr_WindowPtr = (APTR) HackWindow;
  2215.     }
  2216. #ifdef HACKFONT
  2217.     if (HackFont)
  2218.         SetFont(HackWindow->RPort, HackFont);
  2219. #endif
  2220.  
  2221.     ConsoleIO.io_Data = (APTR) HackWindow;
  2222.     ConsoleIO.io_Length = sizeof(*HackWindow);
  2223.     if (OpenDevice("console.device",0L , &ConsoleIO, 0L) != 0)
  2224.         abort(AG_OpenDev | AO_ConsoleDev);
  2225.  
  2226.     ConsoleDevice = ConsoleIO.io_Device;
  2227.  
  2228.     Buffered = 0;
  2229.     KbdBuffered = 0;
  2230.  
  2231.     /* set CRMOD on */
  2232.     WindowFPuts("\x9B20h");
  2233.  
  2234.     Initialized = TRUE;
  2235. }
  2236. SHAR_EOF
  2237. #    End of shell archive
  2238. exit 0
  2239. -- 
  2240. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2241. Have five nice days.
  2242.